package com.urea.system.config;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.urea.common.core.domain.entity.Customer;
import com.urea.common.core.domain.entity.SysUser;
import com.urea.common.core.redis.RedisCache;
import com.urea.common.exception.ServiceException;
import com.urea.common.utils.StringUtils;
import com.urea.common.utils.spring.SpringUtils;
import com.urea.system.constants.BusinessConstants;
import com.urea.system.domain.*;
import com.urea.system.domain.event.FeeEvent;
import com.urea.system.domain.vo.CustomerAccountVo;
import com.urea.system.domain.vo.OrderVo;
import com.urea.system.domain.vo.PayVo;
import com.urea.system.service.*;
import com.urea.system.service.impl.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.urea.system.constants.BusinessConstants.OFFLINE_PAY;
import static com.urea.system.constants.BusinessConstants.ORDER_STATUS_COMPLETE;

/**
 * @Author: liuzd
 * @Date: 2023/7/30 17:06
 * @Description:
 */
@Slf4j
@Component
public class MqttConsumer {

    @Autowired
    private IHardwareService hardwareService;
    @Autowired
    private IOrderService orderService;
    @Autowired
    private ITerminalService terminalService;
    @Autowired
    private ITerminalNoticeService noticeService;
    @Autowired
    private ITerminalLogService logService;
    @Autowired
    private ITerminalCommLogService commLogService;
    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ICustomerAccountService customerAccountService;
    @Value("${wx.miniapp.template}")
    private String templateId ;
    @Autowired
    private MqttConsumerConfig consumerConfig;
    @Value("${spring.mqtt.customerTopic}")
    private String topic;
    @Value("${spring.mqtt.customerTopicCode}")
    private String code;



    @Transactional
    public void messageArrived(String topic, MqttMessage message){
        log.info("#############接收消息主题:{},消息Qos:{},消息内容:{},消息retained:{}#####################",
                topic,message.getQos(),new String(message.getPayload()),message.isRetained());
        JSONObject json = new JSONObject();
        Terminal terminal = null;
        String orderNo = "";
        // 记录通信日志
        TerminalCommLog commLog = new TerminalCommLog();
        commLog.setStatus("1");
        try {
            String msg = new String(message.getPayload());
            if (StringUtils.isBlank(msg)){
                return;
            }
            json = JSONObject.parse(msg);
            if (Objects.nonNull(json)&&StringUtils.equals(json.getString("event"),"config")){
                // 配置回复
                String uid = json.getString("uid");
                // 获取设备信息
                terminal = terminalService.getOne(Wrappers.lambdaQuery(Terminal.class)
                        .eq(Terminal::getTerminalNo, uid).eq(Terminal::getOnline, "1")
                        .eq(Terminal::getAssign, "1"));
                if (Objects.isNull(terminal)){
                    throw new ServiceException("设备未上线或异常!");
                }
                // 获取订单信息,
                Order order = new Order();
                order.setTerminalId(terminal.getId());
                order.setStatus(1);
                order.getParams().put("patMethod",1);
                // 实际加注为null 标识还为完成加注的
                order.getParams().put("extraInfo",1);
                List<OrderVo> orderVos = orderService.selectOrderList(order);
                if (CollectionUtil.isNotEmpty(orderVos)){
                    OrderVo orderVo = orderVos.get(0);
                    // 出货指令
                    hardwareService.run(orderVo.getOrderNo(),orderVo.getCustomerId().toString(),
                            orderVo.getAmount().multiply(new BigDecimal("100")),terminal.getTerminalNo());
                }
            }else if (StringUtils.equals(json.getString("event"),"result")){
                // 确认接受到出货指令
                JSONObject extra = json.getJSONObject("extra");
                orderNo = extra.getString("ser");
                Order order = orderService.getOne(Wrappers.lambdaQuery(Order.class).eq(Order::getOrderNo, orderNo));
                terminal = terminalService.getById(order.getTerminalId());
            }else if (StringUtils.equals(json.getString("event"),"fee")){
                // 结束计费消息
                JSONObject extra = json.getJSONObject("extra");
                FeeEvent feeEvent = extra.toJavaObject(FeeEvent.class);
                orderService.updateOrderFinish(feeEvent);
            }else if (StringUtils.equals(json.getString("event"),"offline")){
                // 设备掉线
                String terminalNo = json.getString("uid");
                TerminalNotice notice = new TerminalNotice();
                Terminal one = terminalService.getOne(Wrappers.lambdaQuery(Terminal.class).eq(Terminal::getTerminalNo, terminalNo));
                notice.setTerminalId(one.getId());
                notice.setNoticeType(0);
                notice.setTerminalCapacity(one.getCurrentCapacity());
                notice.setNotice("设备离线");
                noticeService.save(notice);
                terminalService.update(Wrappers.lambdaUpdate(Terminal.class).eq(Terminal::getId,one.getId())
                        .set(Terminal::getOnline,0));
                commLog.setTerminalNo(terminalNo);
            }else if (StringUtils.equals(json.getString("event"),"online")){
                // 设备上线
                String terminalNo = json.getString("uid");
                Terminal one = terminalService.getOne(Wrappers.lambdaQuery(Terminal.class).eq(Terminal::getTerminalNo, terminalNo));
                noticeService.update(Wrappers.lambdaUpdate(TerminalNotice.class).eq(TerminalNotice::getId,one.getId())
                        .eq(TerminalNotice::getNoticeType,"0")
                        .eq(TerminalNotice::getNotice,"设备离线")
                        .set(TerminalNotice::getStatus,"0")
                        .set(TerminalNotice::getUpdatedTime,LocalDateTime.now()));
                terminalService.update(Wrappers.lambdaUpdate(Terminal.class).eq(Terminal::getId,one.getId())
                        .set(Terminal::getOnline,1));
                commLog.setTerminalNo(terminalNo);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("#################消费消息异常:{}####################",e.getMessage());
            if (StringUtils.isBlank(json.getString("event"))||StringUtils.isBlank(json.getString("uid"))){
                return;
            }
            String terminalNo = json.getString("uid");
            TerminalNotice notice = new TerminalNotice();
            Terminal one = terminalService.getOne(Wrappers.lambdaQuery(Terminal.class).eq(Terminal::getTerminalNo, terminalNo));
            notice.setTerminalId(one.getId());
            notice.setNoticeType(1);
            notice.setTerminalCapacity(one.getCurrentCapacity());
            notice.setNotice("接收硬件信息失败");
            noticeService.save(notice);
            commLog.setStatus("0");
        }
        if (Objects.nonNull(terminal)){
            commLog.setTerminalId(terminal.getId());
            commLog.setTerminalNo(terminal.getTerminalNo());
        }
        commLog.setCommType(json.getString("event"));
        commLog.setContent(json.toString());
        commLog.setSerialNo(orderNo);
        commLogService.save(commLog);

    }

    public void connect(){
        consumerConfig.connect();
    }

    public void subscribe(){
        // 获取所有已经分配的设备信息
        List<Terminal> list = terminalService.list();
        if (CollectionUtil.isNotEmpty(list)){
            List<String> collect = list.stream().map(Terminal::getTerminalNo).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(collect)){
//                int[] qos = new int[collect.size()];
//                String[] topics = new String[collect.size()];
                for (int i = 0; i < collect.size(); i++) {
//                    qos[i] = 1;
//                    topics[i] = topic.concat(collect.get(i)).concat(code);
                    String topicName = topic.concat(collect.get(i)).concat(code);
                    consumerConfig.subscribe(topicName,1);
                    log.info("############订阅主题:{}成功############",topicName);
                }
            }
        }
    }



}